package com.minggo.charmword.net;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpMethodParams;

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.minggo.charmword.model.Result;

/**
 * 接口调用端
 * 
 * @author minggo
 * @date 2014-9-15 上午11:22:04
 */
public class ApiClient {
	public static final String UTF_8 = "UTF-8";

	private final static int TIMEOUT_CONNECTION = 15000;
	private final static int TIMEOUT_SOCKET = 15000;
	private final static int RETRY_TIME = 0;

	private static String appUserAgent;

	private static String getUserAgent() {
		if (appUserAgent == null || appUserAgent == "") {
			StringBuilder ua = new StringBuilder();
			ua.append("/Android");// 手机系统平台
			ua.append("/" + android.os.Build.VERSION.RELEASE);// 手机系统版本
			ua.append("/" + android.os.Build.MODEL); // 手机型号
			ua.append("/" + Locale.getDefault().toString()); // 手机语言
			appUserAgent = ua.toString();
		}
		return appUserAgent;
	}

	private static HttpClient getHttpClient() {
		HttpClient httpClient = new HttpClient();
		// 设置 HttpClient 接收 Cookie,用与浏览器一样的策略
		httpClient.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
		// 设置 默认的超时重试处理策略
		httpClient.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
		// 设置 连接超时时间
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(TIMEOUT_CONNECTION);

		httpClient.getHttpConnectionManager().getParams().setParameter("http.socket.timeout", TIMEOUT_SOCKET);
		// 设置 读数据超时时间
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(TIMEOUT_SOCKET);
		// 设置 字符集
		httpClient.getParams().setContentCharset(UTF_8);
		return httpClient;

		// return (HttpClient) HttpClientFactory.getHttpClient();
	}

	private static GetMethod getHttpGet(String url, String cookie, String userAgent) {
		GetMethod httpGet = new GetMethod(url);
		// 设置 请求超时时间
		httpGet.getParams().setSoTimeout(TIMEOUT_SOCKET);
		httpGet.setRequestHeader("Connection", "Keep-Alive");
		// httpGet.setRequestHeader("Cookie", cookie);
		httpGet.setRequestHeader("User-Agent", userAgent);
		return httpGet;
	}

	private static PostMethod getHttpPost(String url, String cookie, String userAgent) {
		PostMethod httpPost = new PostMethod(url);
		// 设置 请求超时时间
		httpPost.getParams().setSoTimeout(TIMEOUT_SOCKET);
		httpPost.setRequestHeader("Connection", "Keep-Alive");
		// httpPost.setRequestHeader("Cookie", cookie);
		httpPost.setRequestHeader("User-Agent", userAgent);
		return httpPost;
	}

	public static String _MakeURL(String p_url, Map<String, Object> params) {
		StringBuilder url = new StringBuilder(p_url);
		if (url.indexOf("?") < 0)
			url.append('?');

		for (String name : params.keySet()) {
			url.append('&');
			url.append(name);
			url.append('=');
			url.append(String.valueOf(params.get(name)));
		}

		return url.toString().replace("?&", "?");
	}

	/**
	 * get请求URL
	 * 
	 * @param url
	 *            url地址
	 * @param params
	 *            参数
	 * @param isphp
	 *            是否是php接口
	 * @return
	 * @throws Exception
	 */
	public static Result http_get(String url, Map<String, Object> params, boolean isphp, boolean keepChangeLine)
			throws Exception {
		return http_get(url, params, isphp, true, keepChangeLine);
	}

	/**
	 * get请求URL
	 * 
	 * @param url
	 *            不完整url地址
	 * @param params
	 *            参数
	 * @param isphp
	 *            是否是php接口
	 * @param isjson
	 *            是否需要转换为json
	 * @return
	 * @throws Exception
	 */
	public static Result http_get(String url, Map<String, Object> params, boolean isphp, boolean isjson,
			boolean keepChangeLine) throws Exception {

		String urlTemp = url;

		String userAgent = getUserAgent();
		HttpClient httpClient = null;
		GetMethod httpGet = null;

		String responseBody = "";
		int time = 0;
		do {
			try {
				url = ApiUrl.DOMAIN + urlTemp;// 加上域名URL
				url = _MakeURL(url, params);
				Log.i("net", "URL--->" + url);
				httpClient = getHttpClient();

				httpGet = getHttpGet(url, null, userAgent);
				int statusCode = httpClient.executeMethod(httpGet);

				if (statusCode == 200 || statusCode == 404 || statusCode == 302 || statusCode == 301
						|| statusCode == 504 || statusCode == 502) {
					responseBody = toString(httpGet.getResponseBodyAsStream(), "utf-8", keepChangeLine);
					Log.i("net", "responseBody--->" + responseBody);
					break;
				}
			} catch (HttpException e) {
				time++;
				e.printStackTrace();
			} catch (IOException e) {
				time++;

				e.printStackTrace();
			} finally {
				if (httpGet != null) {
					httpGet.releaseConnection();
				}
				httpClient = null;
			}
		} while (time < RETRY_TIME);

		if (responseBody == null || responseBody.equals("")) {
			return null;
		}
		Result result = null;

		Gson gson = new Gson();
		try {
			result = gson.fromJson(responseBody, Result.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * get请求URL
	 * 
	 * @param url
	 *            完整url地址
	 * @param isphp
	 *            是否是php接口
	 * @param isjson
	 *            是否需要转换为json
	 * @return
	 * @throws Exception
	 */
	public static Result http_getWithFullUrl(String url, boolean isphp, boolean isjson, boolean keepChangeLine)
			throws Exception {

		String userAgent = getUserAgent();
		HttpClient httpClient = null;
		GetMethod httpGet = null;

		String responseBody = "";
		int time = 0;
		do {
			try {
				httpClient = getHttpClient();
				httpGet = getHttpGet(url, null, userAgent);
				int statusCode = httpClient.executeMethod(httpGet);

				if (statusCode == 200 || statusCode == 404 || statusCode == 302 || statusCode == 301
						|| statusCode == 504 || statusCode == 502) {
					responseBody = toString(httpGet.getResponseBodyAsStream(), "utf-8", keepChangeLine);
					break;
				}
			} catch (HttpException e) {
				time++;

				e.printStackTrace();
			} catch (IOException e) {
				time++;
				e.printStackTrace();
			} finally {
				if (httpGet != null) {
					httpGet.releaseConnection();
				}
				httpClient = null;
			}
		} while (time < RETRY_TIME);

		if (responseBody == null || responseBody == "") {
			return null;
		}

		Result result = null;

		if (!isjson) {
			result = new Result();
			result.content = responseBody;
			return result;
		}

		Gson gson = new Gson();
		try {
			result = gson.fromJson(responseBody, Result.class);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 公用post方法
	 * 
	 * @param url
	 * @param params
	 * @param files
	 * @throws Exception
	 */
	public static Result _post(String url, Map<String, Object> params, Map<String, File> files, boolean keepChangeLine)
			throws Exception {
		return _post(url, params, files, false, keepChangeLine);
	}

	/**
	 * 公用post方法
	 * 
	 * @param url
	 * @param params
	 * @param files
	 * @throws Exception
	 */
	public static Result _post(String url, Map<String, Object> params, Map<String, File> files, boolean isphp,
			boolean keepChangeLine) throws Exception {

		String urlTemp = url;
		String userAgent = getUserAgent();

		HttpClient httpClient = null;
		PostMethod httpPost = null;

		int length = (params == null ? 0 : params.size()) + (files == null ? 0 : files.size());
		Part[] parts = new Part[length];
		int i = 0;
		if (params != null)
			for (String name : params.keySet()) {
				parts[i++] = new StringPart(name, String.valueOf(params.get(name)), UTF_8);
			}

		if (files != null)
			for (String file : files.keySet()) {
				try {
					parts[i++] = new FilePart(file, files.get(file));
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
			}

		String responseBody = "";
		int time = 0;
		do {
			try {

				url = ApiUrl.DOMAIN + urlTemp;// 加上域名URL
				Log.i("charmword", "postUrl-->"+url);
				httpClient = getHttpClient();
				httpPost = getHttpPost(url, null, userAgent);
				httpPost.setRequestEntity(new MultipartRequestEntity(parts, httpPost.getParams()));
				int statusCode = httpClient.executeMethod(httpPost);

				if (statusCode == 200 || statusCode == 404 || statusCode == 302 || statusCode == 301
						|| statusCode == 504 || statusCode == 502) {
					responseBody = toString(httpPost.getResponseBodyAsStream(), "utf-8", keepChangeLine);
					Log.i("charmword", "postResponse-->"+responseBody);
					break;
				}
			} catch (HttpException e) {
				time++;
				e.printStackTrace();
			} catch (IOException e) {
				time++;
				e.printStackTrace();
			} catch (Exception e) {
				time++;

				e.printStackTrace();
			} finally {
				httpPost.releaseConnection();
				httpClient = null;
			}
		} while (time < RETRY_TIME);

		GsonBuilder builder = new GsonBuilder();
		Gson gson = builder.create();
		Result result = gson.fromJson(responseBody, Result.class);
		return result;
	}

	/**
	 * 将输入流转为字符串,流会被关闭
	 * 
	 * @param in
	 * @param decoding
	 *            解码方式，默认为utf-8
	 * @param keepChangeLine
	 *            保持换行符keepChangeLine
	 * @return 异常时返回空串
	 */
	private static final String toString(InputStream in, String decoding, boolean keepChangeLine) {
		if (in == null) {
			return "";
		} else {
			if (TextUtils.isEmpty(decoding)) {
				decoding = "utf-8";
			}

			InputStreamReader isr = null;
			BufferedReader br = null;
			StringBuilder sb = new StringBuilder();

			try {
				isr = new InputStreamReader(in, decoding);
				br = new BufferedReader(isr);
				String temp;
				while ((temp = br.readLine()) != null) {
					if (keepChangeLine) {
						sb.append(temp + "\n");
					} else {
						sb.append(temp);
					}
				}
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					if (in != null) {
						in.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					try {
						if (isr != null) {
							isr.close();
						}
					} catch (IOException e) {
						e.printStackTrace();
					} finally {
						try {
							if (br != null) {
								br.close();
							}
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}
			return sb.toString();

		}
	}
}
